using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;

namespace CKY.AgentPlatform.ModelConfigs
{
    /// <summary>
    /// 监控指标类型
    /// </summary>
    public enum MetricType
    {
        /// <summary>
        /// 计数器
        /// </summary>
        Counter,

        /// <summary>
        /// 测量值
        /// </summary>
        Gauge,

        /// <summary>
        /// 直方图
        /// </summary>
        Histogram,

        /// <summary>
        /// 计时器
        /// </summary>
        Timer
    }

    /// <summary>
    /// 监控指标
    /// </summary>
    public class Metric
    {
        /// <summary>
        /// 指标名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 指标类型
        /// </summary>
        public MetricType Type { get; set; }

        /// <summary>
        /// 指标值
        /// </summary>
        public double Value { get; set; }

        /// <summary>
        /// 标签
        /// </summary>
        public Dictionary<string, string> Tags { get; set; } = new();

        /// <summary>
        /// 时间戳
        /// </summary>
        public DateTime Timestamp { get; set; } = DateTime.UtcNow;

        /// <summary>
        /// 描述
        /// </summary>
        public string Description { get; set; }
    }

    /// <summary>
    /// 性能指标
    /// </summary>
    public class PerformanceMetrics
    {
        /// <summary>
        /// 总请求数
        /// </summary>
        public long TotalRequests { get; set; }

        /// <summary>
        /// 成功请求数
        /// </summary>
        public long SuccessRequests { get; set; }

        /// <summary>
        /// 失败请求数
        /// </summary>
        public long FailedRequests { get; set; }

        /// <summary>
        /// 平均响应时间（毫秒）
        /// </summary>
        public double AverageResponseTimeMs { get; set; }

        /// <summary>
        /// 最小响应时间（毫秒）
        /// </summary>
        public double MinResponseTimeMs { get; set; }

        /// <summary>
        /// 最大响应时间（毫秒）
        /// </summary>
        public double MaxResponseTimeMs { get; set; }

        /// <summary>
        /// P95响应时间（毫秒）
        /// </summary>
        public double P95ResponseTimeMs { get; set; }

        /// <summary>
        /// P99响应时间（毫秒）
        /// </summary>
        public double P99ResponseTimeMs { get; set; }

        /// <summary>
        /// 成功率
        /// </summary>
        public double SuccessRate { get; set; }

        /// <summary>
        /// 错误率
        /// </summary>
        public double ErrorRate { get; set; }

        /// <summary>
        /// 每秒请求数
        /// </summary>
        public double RequestsPerSecond { get; set; }

        /// <summary>
        /// 总Token使用量
        /// </summary>
        public long TotalTokensUsed { get; set; }

        /// <summary>
        /// 平均Token使用量
        /// </summary>
        public double AverageTokensUsed { get; set; }

        /// <summary>
        /// 统计开始时间
        /// </summary>
        public DateTime StartTime { get; set; }

        /// <summary>
        /// 统计结束时间
        /// </summary>
        public DateTime EndTime { get; set; }
    }

    /// <summary>
    /// 模型执行记录
    /// </summary>
    public class ModelExecutionRecord
    {
        /// <summary>
        /// 执行ID
        /// </summary>
        public string ExecutionId { get; set; }

        /// <summary>
        /// 模型配置ID
        /// </summary>
        public Guid ModelConfigId { get; set; }

        /// <summary>
        /// 模型提供商
        /// </summary>
        public ModelProvider Provider { get; set; }

        /// <summary>
        /// 模型名称
        /// </summary>
        public string ModelName { get; set; }

        /// <summary>
        /// API模式
        /// </summary>
        public ModelApiMode ApiMode { get; set; }

        /// <summary>
        /// 适配器名称
        /// </summary>
        public string AdapterName { get; set; }

        /// <summary>
        /// 用户ID
        /// </summary>
        public string UserId { get; set; }

        /// <summary>
        /// 会话ID
        /// </summary>
        public string SessionId { get; set; }

        /// <summary>
        /// 开始时间
        /// </summary>
        public DateTime StartTime { get; set; }

        /// <summary>
        /// 结束时间
        /// </summary>
        public DateTime EndTime { get; set; }

        /// <summary>
        /// 响应时间（毫秒）
        /// </summary>
        public long ResponseTimeMs { get; set; }

        /// <summary>
        /// 是否成功
        /// </summary>
        public bool Success { get; set; }

        /// <summary>
        /// 错误类型
        /// </summary>
        public ModelErrorType? ErrorType { get; set; }

        /// <summary>
        /// 错误消息
        /// </summary>
        public string ErrorMessage { get; set; }

        /// <summary>
        /// 使用的Token数量
        /// </summary>
        public long TokensUsed { get; set; }

        /// <summary>
        /// 重试次数
        /// </summary>
        public int RetryCount { get; set; }

        /// <summary>
        /// 输入消息数量
        /// </summary>
        public int InputMessageCount { get; set; }

        /// <summary>
        /// 输入字符数
        /// </summary>
        public int InputCharacters { get; set; }

        /// <summary>
        /// 输出字符数
        /// </summary>
        public int OutputCharacters { get; set; }

        /// <summary>
        /// 自定义元数据
        /// </summary>
        public Dictionary<string, object> Metadata { get; set; } = new();
    }

    /// <summary>
    /// 监控配置
    /// </summary>
    public class MonitoringConfig
    {
        /// <summary>
        /// 是否启用监控
        /// </summary>
        public bool Enabled { get; set; } = true;

        /// <summary>
        /// 数据保留时间（小时）
        /// </summary>
        public int DataRetentionHours { get; set; } = 168; // 7天

        /// <summary>
        /// 最大记录数
        /// </summary>
        public int MaxRecords { get; set; } = 10000;

        /// <summary>
        /// 统计聚合间隔（秒）
        /// </summary>
        public int AggregationIntervalSeconds { get; set; } = 60;

        /// <summary>
        /// 是否启用详细日志
        /// </summary>
        public bool EnableDetailedLogging { get; set; } = true;

        /// <summary>
        /// 性能警告阈值（毫秒）
        /// </summary>
        public int PerformanceWarningThresholdMs { get; set; } = 5000;

        /// <summary>
        /// 错误率警告阈值（0-1）
        /// </summary>
        public double ErrorRateWarningThreshold { get; set; } = 0.1;

        /// <summary>
        /// 是否启用实时指标
        /// </summary>
        public bool EnableRealTimeMetrics { get; set; } = true;
    }

    /// <summary>
    /// 模型监控服务
    /// </summary>
    public class ModelMonitoringService
    {
        private readonly MonitoringConfig _config;
        private readonly ILogger<ModelMonitoringService> _logger;
        private readonly ConcurrentQueue<ModelExecutionRecord> _executionRecords = new();
        private readonly ConcurrentDictionary<string, Metric> _metrics = new();
        private readonly Timer _cleanupTimer;
        private readonly Timer _aggregationTimer;

        public ModelMonitoringService(MonitoringConfig config, ILogger<ModelMonitoringService> logger)
        {
            _config = config ?? throw new ArgumentNullException(nameof(config));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));

            // 初始化清理定时器
            _cleanupTimer = new Timer(CleanupOldRecords, null, TimeSpan.FromHours(1), TimeSpan.FromHours(1));

            // 初始化聚合定时器
            if (_config.EnableRealTimeMetrics)
            {
                _aggregationTimer = new Timer(AggregateMetrics, null,
                    TimeSpan.FromSeconds(_config.AggregationIntervalSeconds),
                    TimeSpan.FromSeconds(_config.AggregationIntervalSeconds));
            }
        }

        /// <summary>
        /// 记录模型执行
        /// </summary>
        /// <param name="record">执行记录</param>
        public void RecordExecution(ModelExecutionRecord record)
        {
            if (!_config.Enabled) return;

            try
            {
                record.EndTime = DateTime.UtcNow;
                record.ResponseTimeMs = (long)(record.EndTime - record.StartTime).TotalMilliseconds;

                // 添加到记录队列
                _executionRecords.Enqueue(record);

                // 限制队列大小
                while (_executionRecords.Count > _config.MaxRecords)
                {
                    _executionRecords.TryDequeue(out _);
                }

                // 更新指标
                UpdateMetrics(record);

                // 性能警告
                if (record.ResponseTimeMs > _config.PerformanceWarningThresholdMs)
                {
                    _logger.LogWarning("性能警告: 模型 {ModelName} 响应时间过长 {ResponseTimeMs}ms",
                        record.ModelName, record.ResponseTimeMs);
                }

                // 详细日志
                if (_config.EnableDetailedLogging)
                {
                    _logger.LogInformation("模型执行记录: {ExecutionId}, 模型: {ModelName}, 成功: {Success}, 耗时: {ResponseTimeMs}ms, Token: {TokensUsed}",
                        record.ExecutionId, record.ModelName, record.Success, record.ResponseTimeMs, record.TokensUsed);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "记录模型执行失败");
            }
        }

        /// <summary>
        /// 更新指标
        /// </summary>
        /// <param name="record">执行记录</param>
        private void UpdateMetrics(ModelExecutionRecord record)
        {
            // 总请求数
            IncrementCounter("model_requests_total", new Dictionary<string, string>
            {
                ["provider"] = record.Provider.ToString(),
                ["model"] = record.ModelName,
                ["api_mode"] = record.ApiMode.ToString(),
                ["success"] = record.Success.ToString().ToLower()
            });

            // 响应时间
            RecordTimer("model_response_time_ms", record.ResponseTimeMs, new Dictionary<string, string>
            {
                ["provider"] = record.Provider.ToString(),
                ["model"] = record.ModelName
            });

            // Token使用量
            IncrementCounter("model_tokens_total", new Dictionary<string, string>
            {
                ["provider"] = record.Provider.ToString(),
                ["model"] = record.ModelName
            }, record.TokensUsed);

            // 错误计数
            if (!record.Success)
            {
                IncrementCounter("model_errors_total", new Dictionary<string, string>
                {
                    ["provider"] = record.Provider.ToString(),
                    ["model"] = record.ModelName,
                    ["error_type"] = record.ErrorType?.ToString() ?? "unknown"
                });
            }

            // 重试计数
            if (record.RetryCount > 0)
            {
                IncrementCounter("model_retries_total", new Dictionary<string, string>
                {
                    ["provider"] = record.Provider.ToString(),
                    ["model"] = record.ModelName
                }, record.RetryCount);
            }
        }

        /// <summary>
        /// 增加计数器
        /// </summary>
        /// <param name="name">指标名称</param>
        /// <param name="tags">标签</param>
        /// <param name="value">增加值</param>
        public void IncrementCounter(string name, Dictionary<string, string> tags = null, double value = 1)
        {
            var key = GetMetricKey(name, tags);
            _metrics.AddOrUpdate(key,
                _ => new Metric { Name = name, Type = MetricType.Counter, Value = value, Tags = tags ?? new() },
                (_, existing) => new Metric { Name = name, Type = MetricType.Counter, Value = existing.Value + value, Tags = tags ?? new() });
        }

        /// <summary>
        /// 记录测量值
        /// </summary>
        /// <param name="name">指标名称</param>
        /// <param name="value">值</param>
        /// <param name="tags">标签</param>
        public void RecordGauge(string name, double value, Dictionary<string, string> tags = null)
        {
            var key = GetMetricKey(name, tags);
            _metrics.AddOrUpdate(key,
                _ => new Metric { Name = name, Type = MetricType.Gauge, Value = value, Tags = tags ?? new() },
                (_, existing) => new Metric { Name = name, Type = MetricType.Gauge, Value = value, Tags = tags ?? new() });
        }

        /// <summary>
        /// 记录计时器
        /// </summary>
        /// <param name="name">指标名称</param>
        /// <param name="value">值</param>
        /// <param name="tags">标签</param>
        public void RecordTimer(string name, double value, Dictionary<string, string> tags = null)
        {
            var key = GetMetricKey(name, tags);
            _metrics.AddOrUpdate(key,
                _ => new Metric { Name = name, Type = MetricType.Timer, Value = value, Tags = tags ?? new() },
                (_, existing) => new Metric { Name = name, Type = MetricType.Timer, Value = Math.Max(existing.Value, value), Tags = tags ?? new() });
        }

        /// <summary>
        /// 获取指标键
        /// </summary>
        /// <param name="name">指标名称</param>
        /// <param name="tags">标签</param>
        /// <returns>键</returns>
        private string GetMetricKey(string name, Dictionary<string, string> tags)
        {
            if (tags == null || tags.Count == 0)
                return name;

            var tagString = string.Join(",", tags.OrderBy(kvp => kvp.Key).Select(kvp => $"{kvp.Key}={kvp.Value}"));
            return $"{name}[{tagString}]";
        }

        /// <summary>
        /// 获取性能指标
        /// </summary>
        /// <param name="startTime">开始时间</param>
        /// <param name="endTime">结束时间</param>
        /// <returns>性能指标</returns>
        public PerformanceMetrics GetPerformanceMetrics(DateTime startTime, DateTime endTime)
        {
            var records = _executionRecords.Where(r => r.StartTime >= startTime && r.StartTime <= endTime).ToList();

            if (!records.Any())
            {
                return new PerformanceMetrics
                {
                    TotalRequests = 0,
                    SuccessRequests = 0,
                    FailedRequests = 0,
                    SuccessRate = 0,
                    ErrorRate = 0,
                    StartTime = startTime,
                    EndTime = endTime
                };
            }

            var responseTimes = records.Select(r => r.ResponseTimeMs).ToList();
            var successRecords = records.Where(r => r.Success).ToList();

            return new PerformanceMetrics
            {
                TotalRequests = records.Count,
                SuccessRequests = successRecords.Count,
                FailedRequests = records.Count - successRecords.Count,
                AverageResponseTimeMs = responseTimes.Average(),
                MinResponseTimeMs = responseTimes.Min(),
                MaxResponseTimeMs = responseTimes.Max(),
                P95ResponseTimeMs = CalculatePercentile(responseTimes, 95),
                P99ResponseTimeMs = CalculatePercentile(responseTimes, 99),
                SuccessRate = (double)successRecords.Count / records.Count,
                ErrorRate = (double)(records.Count - successRecords.Count) / records.Count,
                RequestsPerSecond = records.Count / (endTime - startTime).TotalSeconds,
                TotalTokensUsed = records.Sum(r => r.TokensUsed),
                AverageTokensUsed = records.Any() ? records.Average(r => r.TokensUsed) : 0,
                StartTime = startTime,
                EndTime = endTime
            };
        }

        /// <summary>
        /// 计算百分位数
        /// </summary>
        /// <param name="values">值列表</param>
        /// <param name="percentile">百分位</param>
        /// <returns>百分位数值</returns>
        private double CalculatePercentile(List<long> values, double percentile)
        {
            if (!values.Any()) return 0;

            var sorted = values.OrderBy(v => v).ToList();
            var index = (int)Math.Ceiling(percentile / 100 * sorted.Count) - 1;
            return Math.Max(0, sorted[Math.Max(0, Math.Min(index, sorted.Count - 1))]);
        }

        /// <summary>
        /// 获取所有指标
        /// </summary>
        /// <returns>指标列表</returns>
        public IEnumerable<Metric> GetAllMetrics()
        {
            return _metrics.Values.ToList();
        }

        /// <summary>
        /// 获取最近的执行记录
        /// </summary>
        /// <param name="count">数量</param>
        /// <returns>执行记录列表</returns>
        public List<ModelExecutionRecord> GetRecentExecutions(int count = 100)
        {
            return _executionRecords.OrderByDescending(r => r.StartTime).Take(count).ToList();
        }

        /// <summary>
        /// 清理旧记录
        /// </summary>
        /// <param name="state">状态</param>
        private void CleanupOldRecords(object state)
        {
            try
            {
                var cutoff = DateTime.UtcNow.AddHours(-_config.DataRetentionHours);

                while (_executionRecords.TryPeek(out var record) && record.StartTime < cutoff)
                {
                    _executionRecords.TryDequeue(out _);
                }

                _logger.LogDebug("清理了过期执行记录");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "清理旧记录失败");
            }
        }

        /// <summary>
        /// 聚合指标
        /// </summary>
        /// <param name="state">状态</param>
        private void AggregateMetrics(object state)
        {
            try
            {
                var now = DateTime.UtcNow;
                var startTime = now.AddSeconds(-_config.AggregationIntervalSeconds);
                var metrics = GetPerformanceMetrics(startTime, now);

                // 检查错误率警告
                if (metrics.ErrorRate > _config.ErrorRateWarningThreshold)
                {
                    _logger.LogWarning("错误率警告: 当前错误率 {ErrorRate:P2} 超过阈值 {Threshold:P2}",
                        metrics.ErrorRate, _config.ErrorRateWarningThreshold);
                }

                // 记录聚合指标
                RecordGauge("model_success_rate", metrics.SuccessRate);
                RecordGauge("model_error_rate", metrics.ErrorRate);
                RecordGauge("model_avg_response_time_ms", metrics.AverageResponseTimeMs);
                RecordGauge("model_requests_per_second", metrics.RequestsPerSecond);

                _logger.LogDebug("指标聚合完成: 总请求数={TotalRequests}, 成功率={SuccessRate:P2}",
                    metrics.TotalRequests, metrics.SuccessRate);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "指标聚合失败");
            }
        }

        /// <summary>
        /// 获取健康状态
        /// </summary>
        /// <returns>健康状态信息</returns>
        public Dictionary<string, object> GetHealthStatus()
        {
            var now = DateTime.UtcNow;
            var lastMinuteMetrics = GetPerformanceMetrics(now.AddMinutes(-1), now);
            var lastHourMetrics = GetPerformanceMetrics(now.AddHours(-1), now);

            return new Dictionary<string, object>
            {
                ["status"] = lastMinuteMetrics.ErrorRate < _config.ErrorRateWarningThreshold ? "healthy" : "degraded",
                ["last_minute"] = new Dictionary<string, object>
                {
                    ["total_requests"] = lastMinuteMetrics.TotalRequests,
                    ["success_rate"] = lastMinuteMetrics.SuccessRate,
                    ["avg_response_time_ms"] = lastMinuteMetrics.AverageResponseTimeMs,
                    ["requests_per_second"] = lastMinuteMetrics.RequestsPerSecond
                },
                ["last_hour"] = new Dictionary<string, object>
                {
                    ["total_requests"] = lastHourMetrics.TotalRequests,
                    ["success_rate"] = lastHourMetrics.SuccessRate,
                    ["avg_response_time_ms"] = lastHourMetrics.AverageResponseTimeMs,
                    ["requests_per_second"] = lastHourMetrics.RequestsPerSecond
                },
                ["system"] = new Dictionary<string, object>
                {
                    ["total_records"] = _executionRecords.Count,
                    ["total_metrics"] = _metrics.Count,
                    ["monitoring_enabled"] = _config.Enabled,
                    ["data_retention_hours"] = _config.DataRetentionHours
                }
            };
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            _cleanupTimer?.Dispose();
            _aggregationTimer?.Dispose();
        }
    }
}